package com.mtiiot.server;

import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;


import com.mtiiot.util.Constants;
import com.mtiiot.util.Des3;
import com.mtiiot.util.Utils;
import com.mtiiot.proto.Data.Group;

import net.sf.json.JSONObject;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;

/**
 * 接口抽象实现类
 * @author 卢承业
 *
 */
public abstract class BaseDataHandler implements DataHandler {
	private static Logger logger = LogManager.getLogger(BaseDataHandler.class);
	private Group group;
	private String messageCode = "";
	public Group getGroup() {
		return group;
	}


	public void setGroup(Group group) {
		this.group = group;
	}

	@Override
	public void init(Group group) {
		// 08.31
		// 汤工那边在group中的code添加新的字段，
		// 新的：code={code="N_YQ_QCM_RSZZ",messageId="1234567890"}
		// 老的：code=N_YQ_QCM_RSZZ
		// 这里做了兼容两种模式的
		String groupCode = group.getCode();
		if (groupCode.contains("code")){
			JSONObject jsonObject = JSONObject.fromObject(groupCode);
			messageCode = jsonObject.getString("code");
		}else {
			messageCode = group.getCode();
		}
		setGroup(group);
	}


	@Override
	public boolean validateDynamicPwd() {
		try {
			String id=getGroup().getId();
			String insPwd="";
			if(Constants.config.isGetPwdFromRedis()){
				//从redis获取仪器对应密码
				try {
					//insPwd=StoreManager.hGet(Constants.INSPWD_PFEFIX+id);//刘丰提供redis客户端jar包
                    //insPwd=Constants.getRedisService().getCache(Constants.INSPWD_PFEFIX+id);//调用平台redis服务
                    insPwd=Constants.getRedisService().getCache(new MetadataInfo(Constants.config.getSysId()),Constants.INSPWD_PFEFIX+id);//调用平台redis服务
					if(insPwd==null||"".equals(insPwd)){
						//处理业务逻辑异常
						//String gStr = Constants.groupToString(getGroup());
						String warningMsg="调用redis异常,"+"异常信息为:get pwd is null"+
								"\r\n,客户端名字:" + Constants.CLIENT_HOST_NAME +
								"\r\n,客户端IP:" + Constants.CLIENT_HOST_IP ;
						logger.warn(warningMsg);
                        //Constants.getLogService().sendLog(SysName.SYSNAME_NETTY, LogLevel.WARNING,"消息验证","BaseDataHandler","validateDynamicPwd",messageCode+"_"+getGroup().getSeqNo(),warningMsg,Constants.config.getServerIp());
						MetadataInfo logMetadataInfo = new MetadataInfo();
						logMetadataInfo.setSysId(Constants.config.getSysId());
						Constants.getLogService().sendLog(logMetadataInfo,LogLevel.WARNING,messageCode+"_"+getGroup().getSeqNo(),warningMsg);
						return false;
					}
				} catch (Exception e) {
					//处理业务逻辑异常
					String gStr = Constants.groupToString(getGroup());
					String warningMsg="调用redis异常,"+"异常信息为:get pwd is null"+
							"\r\n,客户端名字:" + Constants.CLIENT_HOST_NAME +
							"\r\n,客户端IP:" + Constants.CLIENT_HOST_IP +
							"\r\nGroup内容为:"+gStr;
					logger.warn(warningMsg,e);
                    //Constants.getLogService().sendLog(SysName.SYSNAME_NETTY, LogLevel.WARNING,"消息验证","BaseDataHandler","validateDynamicPwd",messageCode+"_"+getGroup().getSeqNo(),warningMsg,Constants.config.getServerIp());
					MetadataInfo logMetadataInfo = new MetadataInfo();
					logMetadataInfo.setSysId(Constants.config.getSysId());
					Constants.getLogService().sendLog(logMetadataInfo,LogLevel.WARNING,messageCode+"_"+getGroup().getSeqNo(),warningMsg);
					insPwd=Constants.config.getIns().get(id);
				}
			}else{
				insPwd=Constants.config.getIns().get(id);
			}
			if(insPwd==null){
				return false;
			}
			//验证结果
			boolean validateValue=Des3.validateDynamicPwd(getGroup().getDynamicPwd(), insPwd, getGroup().getTime());
			if(validateValue){
				Constants.config.getIns().put(id, insPwd);
			}
			return validateValue;
		} catch (Exception e) {
			logger.error(e.getMessage(),e);
			return false;
		}
	}

	@Override
	public Group handle(){
		String code=messageCode;
		String[] codeArr=code.split("_");
		String reqType=codeArr[0];
		String error="";
		String respBody="";
		if(Constants.REQ_TYPE_Y.equals(reqType)){
			try {
                //error="未调用刘丰jar包,用于测试返回时间,当前返回时间为:"+new SimpleDateFormat("yyyy年MM月dd日 HH时mm分ss秒").format(new Date());
				//刘丰jar包调用
				//respBody= BaseService.sendData(messageCode, String.valueOf(getGroup().getSeqNo()), getGroup().getBody());
                //writeStringToFile(respBody,true);//写备份文件
			} catch (Exception e) {
				//处理业务逻辑异常
				String errorMsg="同步调用异常\r\nseqNo为:"+getGroup().getSeqNo()+"\r\n异常信息为:"+e.getMessage();
				logger.error(errorMsg,e);
                //Constants.getLogService().sendLog(SysName.SYSNAME_INS, LogLevel.ERROR, "netty同步调用处理", "BaseDataHandler", "handle", messageCode + "_" + getGroup().getSeqNo(), errorMsg, Constants.config.getServerIp());
				MetadataInfo logMetadataInfo = new MetadataInfo();
				logMetadataInfo.setSysId(Constants.config.getSysId());
				Constants.getLogService().sendLog(logMetadataInfo,LogLevel.ERROR,messageCode+"_"+getGroup().getSeqNo(),errorMsg);
				error=errorMsg;
			}
		}else if(Constants.REQ_TYPE_N.equals(reqType)){
			//异步调用
			String msgHandleType=Constants.config.getMsgHandleType();
			if(Constants.MESSAGEQUEUE.equals(msgHandleType)||Constants.MESSAGEALl.equals(msgHandleType)){
				//消息开始 进消息队列
				try {
                    String bodyJson=getGroup().getBody();
                    // 存文件和发送消息到KAFKA调用新的方式。2016-09-14
                    /*
					FileInfo fi=Constants.getFastdfsService().storeFile(SysName.SYSNAME_INS,l1Name,l2Name,l3Name,"json",bodyJson.getBytes());
                    if(fi==null){
                        throw new Exception("info:盒子数据存入分布式文件系统失败\r\nid:"+getGroup().getId()+"\r\ncode:"+messageCode);
                    }
                    String jsonKey=fi.getId();
                    Constants.ip.sendData(code, String.valueOf(getGroup().getSeqNo()), getGroup().getId(), getGroup().getTime(),jsonKey);
*/

					/////////////////////////////////////////////////////////////////////////////////////////////
					// 调用fs新接口
					// 1：通过服务netty接口上传文件到分布式文件系统，得到dfsId
					MetadataInfo nettyMetadataInfo = new MetadataInfo();
					nettyMetadataInfo.setSysId(Constants.config.getSysId());
					nettyMetadataInfo.setHost(Constants.config.getServerIp());
					String dfsId = Constants.getNettyService().storeFile(nettyMetadataInfo, getGroup().getId(), String.valueOf(getGroup().getSeqNo()), messageCode, "json", bodyJson.getBytes());
					if ("".equals(dfsId) || dfsId == null){
						throw new Exception("info:盒子数据存入分布式文件系统失败\r\nid:"+getGroup().getId()+"\r\ncode:"+messageCode+"clientIp:"+Constants.CLIENT_HOST_IP);
					}
					String mqServer = Constants.config.getMqServer();
					String l1Name="netty";
					String l2Name=getGroup().getId();
					String l3Name=messageCode.replaceAll("_","-");
					if ("kafka".equals(mqServer)){
						MetadataInfo kafkaMetadataInfo = new MetadataInfo();
						kafkaMetadataInfo.setSysId(Constants.config.getSysId());
						//kafkaMetadataInfo.setHost(Constants.config.getServerIp());
						kafkaMetadataInfo.setHost(Constants.CLIENT_HOST_IP);
						kafkaMetadataInfo.setL1Name(l1Name);
						kafkaMetadataInfo.setL2Name(l2Name);
						kafkaMetadataInfo.setL3Name(l3Name);
						MqInfo mqInfo = new MqInfo();
						mqInfo.setTopic(messageCode);
						String key = String.valueOf((long)bodyJson.hashCode() + System.currentTimeMillis()) + "%" + getGroup().getSeqNo() + "%" + getGroup().getId() + "%" + messageCode + "%" + getGroup().getTime();
						mqInfo.setKey(key);
						mqInfo.setValue(dfsId);
						Constants.getKafkaMqService().produceMessage(kafkaMetadataInfo, mqInfo);
					}else if ("redis".equals(mqServer)) {
						MetadataInfo redisMetadataInfo = new MetadataInfo();
						redisMetadataInfo.setSysId(Constants.config.getSysId());
						//redisMetadataInfo.setHost(Constants.config.getServerIp());
						redisMetadataInfo.setHost(Constants.CLIENT_HOST_IP);
						redisMetadataInfo.setL1Name(l1Name);
						redisMetadataInfo.setL2Name(l2Name);
						redisMetadataInfo.setL3Name(l3Name);
						MqInfo mqInfo = new MqInfo();
						mqInfo.setTopic(messageCode);
						String key = String.valueOf((long)bodyJson.hashCode() + System.currentTimeMillis()) + "%" + getGroup().getSeqNo() + "%" + getGroup().getId() + "%" + messageCode + "%" + getGroup().getTime();
						mqInfo.setKey(key);
						mqInfo.setValue(dfsId);
						Constants.getRedisMqService().produceMessage(redisMetadataInfo,mqInfo);
					}
					///////////////////////////////////////////////////////////////////////////////////////////////
				} catch (Exception e) {
					//消息进消息队列失败,记录日志
					String gStr = Constants.groupToString(getGroup());
					String errorMsg="异步调用异常,信息为:"+e.getMessage()+"\r\ngroup信息为："+gStr;
                    logger.error(errorMsg,e);
					MetadataInfo logMetadataInfo = new MetadataInfo();
					logMetadataInfo.setSysId(Constants.config.getSysId());
					Constants.getLogService().sendLog(logMetadataInfo,LogLevel.ERROR,messageCode+"_"+getGroup().getSeqNo(),errorMsg);
					error=errorMsg;
				}
			}
		}else{
			error=Constants.EXCEPRION_TYPE_CODETYPEERROR;
		}

		Group group = Group.newBuilder()
				.setId(getGroup().getId())
				.setTime(getGroup().getTime())
				.setDynamicPwd(getGroup().getDynamicPwd())
				.setCode(messageCode)
				.setError(error)
						.setSeqNo(getGroup().getSeqNo())
				.setBody(respBody).build();
		return group;
	}

	@Override
	public void writeGroupToFile(byte[] respUtf82){
			try{
				///////////写文件形式  start
				SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
				String currentDate=Constants.config.getPath()+getGroup().getId()+"/"+sdf.format(new Date())+"/"+messageCode+"/";
				File filePathTmp=new File(currentDate);
				if(!filePathTmp.exists()){
					filePathTmp.mkdirs();
				}
				String fileName="["+messageCode+"]"+"-"+getGroup().getId()+"-"+getGroup().getTime();
				String filePath=currentDate+fileName+"_"+getGroup().getSeqNo()+".group";
				Utils.WritebyteArrayToFile(respUtf82, filePath);
				///////////写文件形式  end
			}catch (Exception e){
				String errorMsg="写文件异常\r\nseqNo为:"+getGroup().getSeqNo()+"\r\n异常信息为:"+e.getMessage();
				logger.error(errorMsg,e);
				//PlatFormLog.sendLogError(errorMsg,messageCode);
				//Constants.getLogService().sendLog(SysName.SYSNAME_NETTY, LogLevel.ERROR,"写文件处理","BaseDataHandler","writeStringToFile",messageCode+"_"+getGroup().getSeqNo(),errorMsg,Constants.config.getServerIp());
				MetadataInfo logMetadataInfo = new MetadataInfo();
				logMetadataInfo.setSysId(Constants.config.getSysId());
				Constants.getLogService().sendLog(logMetadataInfo,LogLevel.ERROR,messageCode+"_"+getGroup().getSeqNo(),errorMsg);
			}
	}

	@Override
	public String writeStringToFile(String json,boolean isReturnData){
		String filePath = "";
		try {
			// 2017.01-07,注释掉,不备份文件到本地
			///////////写文件形式  start
			/*SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
			String currentDate=Constants.config.getPath()+getGroup().getId()+"/"+sdf.format(new Date())+"/"+messageCode+"/";
			if(isReturnData){
				currentDate=Constants.config.getPath()+getGroup().getId()+"/"+sdf.format(new Date())+"/"+messageCode+"/returnData/";
			}
			File filePathTmp=new File(currentDate);
			if(!filePathTmp.exists()){
				filePathTmp.mkdirs();
			}
			String fileName=null;
			fileName="["+messageCode+"]"+"-"+getGroup().getId()+"-"+getGroup().getTime();
			filePath=currentDate+fileName+"_"+getGroup().getSeqNo();
			File file=new File(filePath+".json");
			boolean flag=true;
			while(flag){
				if(file.exists()){

					 //String name = "[N_YQ_TES_RPFB]-cb29c9db212341398c62051fc349cfe4-20160815161400523_3318_reupload_1";

					if (filePath.indexOf("reupload") == -1){
						filePath = filePath+"_reupload_1";
					}else {
						int re1 = filePath.lastIndexOf("_")+1;
						int len = filePath.length();
						int num = Integer.valueOf(filePath.substring(re1, len))+1;
						filePath = filePath.substring(0,re1)+num;
					}
					file = new File(filePath+".json");
				}else{
					flag=false;
				}
			}
			filePath=filePath+".json";
			Utils.WriteStringToFile(json, filePath);*/
			/////////////////添加检验数据 到ftp目录 start 20161014 /////////////////
			try{
				if(Constants.config.getTestCode().equals(messageCode)){
					SimpleDateFormat sdf1 = new SimpleDateFormat("yyyyMMddHHmmssSSS");
					String testFilePath=Constants.config.getTestDataPath()+sdf1.format(new Date())+"-["+messageCode+"]"+"-"+getGroup().getId()+"-"+getGroup().getSeqNo()+".json";
					Utils.WriteStringToFile(json, testFilePath);
				}
			}catch (Exception e){
				String errorMsg="写检验文件异常\r\nseqNo为:"+getGroup().getSeqNo()+"\r\n异常信息为:"+e.getMessage();
				logger.error(errorMsg,e);
				//PlatFormLog.sendLogError(errorMsg,messageCode);
				//Constants.getLogService().sendLog(SysName.SYSNAME_NETTY, LogLevel.ERROR,"写文件处理","BaseDataHandler","writeStringToFile",messageCode+"_"+getGroup().getSeqNo(),errorMsg,Constants.config.getServerIp());
				MetadataInfo logMetadataInfo = new MetadataInfo();
				logMetadataInfo.setSysId(Constants.config.getSysId());
				Constants.getLogService().sendLog(logMetadataInfo,LogLevel.ERROR,messageCode+"_"+getGroup().getSeqNo(),errorMsg);
			}
			///////////////////添加检验数据 到ftp目录 end 20161014//////////////////////////////////////////
			return filePath;
			///////////写文件形式  end
		} catch (Exception e) {
			String errorMsg="写文件异常\r\nseqNo为:"+getGroup().getSeqNo()+"\r\n异常信息为:"+e.getMessage();
            logger.error(errorMsg,e);
			//PlatFormLog.sendLogError(errorMsg,messageCode);
            //Constants.getLogService().sendLog(SysName.SYSNAME_NETTY, LogLevel.ERROR,"写文件处理","BaseDataHandler","writeStringToFile",messageCode+"_"+getGroup().getSeqNo(),errorMsg,Constants.config.getServerIp());
			MetadataInfo logMetadataInfo = new MetadataInfo();
			logMetadataInfo.setSysId(Constants.config.getSysId());
			Constants.getLogService().sendLog(logMetadataInfo,LogLevel.ERROR,messageCode+"_"+getGroup().getSeqNo(),errorMsg);
			return null;
		}
	}

	public static Group handleFilure(String error){
		Group group = Group.newBuilder()
				.setId("")
				.setTime("")
				.setDynamicPwd("")
				.setCode("")
				.setError(error)
				.setSeqNo(0)
				.setBody("").build();
		return group;
	}
	
	public static DataHandler getDataHandlerByGroup(Group group) throws ClassNotFoundException, InstantiationException, IllegalAccessException{
		DataHandler	dh=new BaseDataHandlerImpl();
		dh.init(group);
		return dh;
//		String className = "com.mtiiot.boxnettyserver.server.service.impl.BaseDataHandlerImpl";
//		Class cls = Class.forName(className);
//		DataHandler dataHandler = (DataHandler) cls.newInstance();
//		dataHandler.init(group);
//		return dataHandler;
	}

	@Override
	public Group dataProcessCenter(){
		Group group1 = null;
		String code = messageCode;
		if (Constants.N_BX_ERR_MESG.equals(code) || Constants.N_IS_ERR_MESG.equals(code)){
			// 处理盒子仪器的异常信息
			group1 = handleErrorMsg();
		} else if (Constants.N_BX_STA_HSZZ.equals(code)){
			//handleHeartMsg(); // 暂时不将盒子的心跳信息发往日志系统
			group1 = handle();
		} else {
			// 处理其他数据
			group1 = handle();
		}
		return group1;
	}

	@Override
	public Group handleErrorMsg(){
		String error = "",respBody = "";
		String code = messageCode;
		String jsonBody = getGroup().getBody();
		String id = getGroup().getId();
		String time = getGroup().getTime();
		String pwd = getGroup().getDynamicPwd();
		String seqNo = String.valueOf(getGroup().getSeqNo());
		SysName sysName = null;
		try {
			if (StringUtils.isBlank(code) || StringUtils.isBlank(jsonBody)) {
				String flag ="[盒子仪器发送的信息为空.]@"+id+"_"+time+"_"+seqNo;
				error = flag;
				respBody = flag;
			}else{
				// 将异常信息发到日志系统
				JSONObject jsonObject = JSONObject.fromObject(jsonBody);
				String insId = jsonObject.getString("instrumentId");
				String level = jsonObject.getString("level");
				String msg = jsonObject.getString("message");
				String runDate = jsonObject.getString("runDate");
				StringBuilder sb = new StringBuilder();
				if (Constants.N_BX_ERR_MESG.equals(code)){
					sb.append("盒子id:"+id).append("\r\n");
					sysName = SysName.SYSNAME_BOX;
				} else if (Constants.N_IS_ERR_MESG.equals(code)){
					sysName = SysName.SYSNAME_OUTINS;
				}
				// 格式化一下盒子仪器信息的显示
				sb.append("仪器id:" + insId).append("\r\n").append("发生时间:"+runDate).append("\r\n");
				sb.append("级别:"+level).append("  \r\n").append("信息:\r\n").append(msg);
				jsonBody = sb.toString();
				// 调用日志接口
				//Constants.getLogService().sendLog(sysName, LogLevel.valueOf(level.toUpperCase()), "盒子仪器信息处理", "BaseDataHandler", "handleErrorMsg", code + "_" + seqNo, jsonBody, Constants.config.getServerIp());
				MetadataInfo logMetadataInfo = new MetadataInfo();
				logMetadataInfo.setSysId(Constants.config.getBoxSysId());
				Constants.getLogService().sendLog(logMetadataInfo,LogLevel.valueOf(level.toUpperCase()),messageCode+"_"+getGroup().getSeqNo(),jsonBody);
			}
		} catch (Exception e){
			String flag = "[处理盒子仪器信息失败]@"+id+"_"+time+"_"+seqNo+"\r\n"+e.getMessage();
			error = flag;
			respBody = flag;
			//Constants.getLogService().sendLog(sysName,LogLevel.ERROR,"盒子仪器信息处理","BaseDataHandler","handleErrorMsg",code + "_" + seqNo,flag,Constants.config.getServerIp());
			MetadataInfo logMetadataInfo = new MetadataInfo();
			logMetadataInfo.setSysId(Constants.config.getBoxSysId());
			Constants.getLogService().sendLog(logMetadataInfo,LogLevel.ERROR,messageCode+"_"+getGroup().getSeqNo(),flag);
			logger.error(flag,e);
		}
		Group group = Group.newBuilder()
				.setId(id)
				.setTime(time)
				.setDynamicPwd(pwd)
				.setCode(code)
				.setError(error)
				.setSeqNo(getGroup().getSeqNo())
				.setBody(respBody).build();
		return group;
	}

	@Override
	public Group handleHeartMsg(){
		String error = "",respBody = "";
		String code = messageCode;
		String jsonBody = getGroup().getBody();
		String id = getGroup().getId();
		String time = getGroup().getTime();
		String pwd = getGroup().getDynamicPwd();
		String seqNo = String.valueOf(getGroup().getSeqNo());
		try {
			if (StringUtils.isBlank(code) || StringUtils.isBlank(jsonBody)) {
				String flag ="[盒子发送的心跳信息为空.]@"+code+"_"+id+"_"+time+"_"+seqNo;
				error = flag;
				respBody = flag;
			}else{
				// 将异常信息发到日志系统
				/*JSONObject jsonObject = JSONObject.fromObject(jsonBody);
				StringBuilder sb = new StringBuilder();
				sb.append("盒子ID:"+jsonObject.getString("boxId")+"\r\n");
				sb.append("盒子版本:"+jsonObject.getString("softwareVersion")+"\r\n");
				sb.append("内存使用:"+jsonObject.getString("memUsed")+"\r\n");
				sb.append("内存大小:"+jsonObject.getString("memTotal")+"\r\n");
				sb.append("CPU使用:"+jsonObject.getString("cpuUsed")+"\r\n");
				sb.append("CPU温度:"+jsonObject.getString("cpuCelsius")+"\r\n");
				sb.append("flash卡大小:"+jsonObject.getString("flashSize")+"\r\n");
				sb.append("flash卡使用率:"+jsonObject.getString("flashUsage")+"\r\n");
				sb.append("sdcard卡使用率:"+jsonObject.getString("sdcardUsage")+"\r\n");
				sb.append("sdcard卡大小:"+jsonObject.getString("sdcardSize")+"\r\n");
				sb.append("盒子电池:"+jsonObject.getString("boxBattery")+"\r\n");
				sb.append("盒子网络:"+jsonObject.getString("boxNet")+"\r\n");
				sb.append("直流状态:"+jsonObject.getString("boxDc")+"\r\n");
				sb.append("运动时长:"+jsonObject.getString("boxUptime")+"\r\n");
				sb.append("传感器温度:"+jsonObject.getString("boxHumi")+"\r\n");
				sb.append("心跳时间:"+jsonObject.getString("runDate")+"\r\n");*/
				// 调用日志接口
				//Constants.getLogService().sendLog(SysName.SYSNAME_BOX, LogLevel.IINFO,"盒子心跳信息处理","BaseDataHandler","handleHeartMsg",code + "_" + seqNo,jsonBody,Constants.config.getServerIp());
			}
		} catch (Exception e){
			String flag = "[处理盒子心跳信息失败]@"+id+"_"+time+"_"+seqNo+"\r\n"+e.getMessage();
			error = flag;
			respBody = flag;
			//Constants.getLogService().sendLog(SysName.SYSNAME_BOX,LogLevel.ERROR,"盒子心跳信息处理","BaseDataHandler","handleHeartMsg",code + "_" + seqNo,flag,Constants.config.getServerIp());
			MetadataInfo logMetadataInfo = new MetadataInfo();
			logMetadataInfo.setSysId(Constants.config.getBoxSysId());
			Constants.getLogService().sendLog(logMetadataInfo,LogLevel.ERROR,messageCode+"_"+getGroup().getSeqNo(),flag);
			logger.error(flag,e);
		}
		Group group = Group.newBuilder()
				.setId(id)
				.setTime(time)
				.setDynamicPwd(pwd)
				.setCode(code)
				.setError(error)
				.setSeqNo(getGroup().getSeqNo())
				.setBody(respBody).build();
		return group;
	}
}
